package org.jspar.temp;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.jspar.model.Direction;
import org.jspar.model.Module;
import org.jspar.model.ModuleModel;
import org.jspar.model.Net;
import org.jspar.model.NetList;
import org.jspar.model.Terminal;
import org.jspar.model.TerminalModel;

@SuppressWarnings("serial")
public class ViewRouting extends JFrame {
	
	public ViewRouting(final NetList netList) {
		setTitle("View Routing");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		final GlobalRouting routing = new GlobalRouting();
		routing.buildTileSpaces(netList);
		routing.makeInitialExpansions(netList);
		
		final TileView view = new TileView(routing);
		getContentPane().add(view, BorderLayout.CENTER);
		
		final JList list = new JList(new ExpansionListModel(routing));
		list.setBorder(new BevelBorder(BevelBorder.LOWERED));
		list.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent e) {
				Expansion ex = (Expansion) list.getSelectedValue();
				view.setExpansion(ex);
			}
		});
		getContentPane().add(list, BorderLayout.EAST);
		
		JPanel buttonBar = new JPanel();
		getContentPane().add(buttonBar, BorderLayout.SOUTH);
		JButton refresh = new JButton("Refresh");
		buttonBar.add(refresh);
		refresh.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				list.setModel(new ExpansionListModel(routing));
				repaint();
			}
		});
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				routing.run(netList);
			}
		}, "routing").start();
		pack();
	}
	
	public static void main(String[] args) {
		NetList netList = createNetList();
		ViewRouting view = new ViewRouting(netList);
		view.setVisible(true);
	}

	private static NetList createNetList() {
		NetList netList = new NetList();
		ModuleModel type = new ModuleModel("NAND", 8, 6);
		type.addTerminal(new TerminalModel("s", 9, 1, Terminal.RIGHT, Direction.OUT));
		type.addTerminal(new TerminalModel("a", -1, 1, Terminal.LEFT, Direction.IN));
		type.addTerminal(new TerminalModel("b", -1, 2, Terminal.LEFT, Direction.IN));
		type.addTerminal(new TerminalModel("c", -1, 3, Terminal.LEFT, Direction.IN));
		Module nand1 = createModule(netList, "nand.1", 32, 0, type);
		Module nand2 = createModule(netList, "nand.2", 9, 20, type);
		Module nand3 = createModule(netList, "nand.3", 15, 34, type);
		Module nand4 = createModule(netList, "nand.4", 9, 1, type);
		Module nand5 = createModule(netList, "nand.5", 32, 19, type);
		Module nand6 = createModule(netList, "nand.6", 52, 19, type);
		Net w = new Net("w");
		w.addTerminal(nand1.getTerminal("s"));
		w.addTerminal(nand2.getTerminal("a"));
		netList.addNet(w);
		Net z = new Net("z");
		z.addTerminal(nand2.getTerminal("s"));
		z.addTerminal(nand5.getTerminal("b"));
		z.addTerminal(nand1.getTerminal("c"));
		z.addTerminal(nand3.getTerminal("a"));
		netList.addNet(z);
		Net y = new Net("y");
		y.addTerminal(nand3.getTerminal("s"));
		y.addTerminal(nand6.getTerminal("c"));
		y.addTerminal(nand4.getTerminal("a"));
		netList.addNet(y);
		Net x = new Net("x");
		x.addTerminal(nand4.getTerminal("s"));
		x.addTerminal(nand1.getTerminal("b"));
		x.addTerminal(nand3.getTerminal("c"));
		netList.addNet(x);
		return netList;
	}
	
	private static Module createModule(NetList netList, String name, int x, int y, ModuleModel model) {
		Module mod;
		netList.addModule(mod = new Module(name, model));
		mod.setPosition(x, y);
		for (TerminalModel tModel : model.getTerminals()) {
			Terminal t = tModel.create(mod);
			mod.addTerminal(t);
			if (t.type() == Direction.OUT) {
				mod.setPrimaryOut(t);
			}
		}
		return mod;
	}
}
